#!/usr/bin/python
# -*- coding: utf-8 -*-
# AUTHOR:   yemd
# FILENAME: py_cluster_stat_manager.py
# DESCRIBE: master-slave server cluster stat manager
# CREATED:  2014-01-15 10:52
# MODIFIED: 2014-01-15 10:52


import sys,os
import inspect
from py_common_log import *

class server_list():
    def __init__(self):
        self._num = -1     #服务器编号
        self._times = 0    #使用次数
        self._mark = 0     #mark值
        self._next = None
        self._cn_ = self.__class__.__name__


class PY_Cluster_Stat_Manager():
    def __init__(self):
        #print self.__class__.__name__   ##打印出类名
        self._downnum = 0
        self._u_start = None
        self._u_end = None
        self._d_start = None
        self._d_end = None
    
    def print_list(self):
        fn = inspect.currentframe().f_code.co_name
        #sel = server_list()
        sel = self._u_start
        if sel:
            DEBUG_LOG(fn,"-----------------up_server_list_print---------------")
        while sel is not None:
            DEBUG_LOG(fn,"up::num-times-mark",sel._num,sel._times,sel._mark)
            sel = sel._next
        
        sel = self._d_start
        if sel:
            DEBUG_LOG(fn,"-----------------down_server_list_print---------------")
            DEBUG_LOG(fn,"all_downnum",self._downnum)
        while sel is not None:
            DEBUG_LOG(fn,"down::num-times-mark",sel._num,sel._times,sel._mark)
            sel = sel._next

    
    def get_down_num(self):
        return self._downnum

    #
    # 添加一个可用服务器，每次在链表最后位置添加
    #
    def add_u_server(self,num,mark):
        fn = inspect.currentframe().f_code.co_name
        sel = server_list()
        sel._num = num
        sel._times = mark
        sel._mark = mark
        if self._u_end:
            self._u_end._next = sel
            self._u_end = sel
        else:
            self._u_end = sel
            self._u_start = sel
        DEBUG_LOG(fn,"u_end::num-mark",self._u_end._num,self._u_end._mark)
        DEBUG_LOG(fn,"u_start::num-mark",self._u_start._num,self._u_start._mark)
        
    
    #
    # 添加一个不可用服务器，每次在链表最后位置添加
    #
    def add_d_server(self,num,mark):
        fn = inspect.currentframe().f_code.co_name
        sel = server_list()
        sel._num = num
        sel._times = mark
        sel._mark = mark
        if self._d_end:
            self._d_end._next = sel
            self._d_end = sel
        else:
            self._d_end = sel
            self._d_start = sel
        DEBUG_LOG(fn,"d_end::num-mark",self._d_end._num,self._d_end._mark)
        DEBUG_LOG(fn,"d_start::num-mark",self._d_start._num,self._d_start._mark)
        DEBUG_LOG(fn,"before::downnum",self._downnum)
        self._downnum = self._downnum + 1
        DEBUG_LOG(fn,"after::downnum",self._downnum)

    
    #
    #获取第一个不可用服务器的编号
    #
    def get_d_first(self):
        fn = inspect.currentframe().f_code.co_name
        if not self._downnum or not self._d_start:
            return -1
        DEBUG_LOG(fn,"first_d_server_num",str(self._d_start._num))
        return self._d_start._num
    

    #
    #挂掉第一个可用服务器,并将此服务器加入down链表
    #当前可使用的服务器一定是在第一个位置
    #
    def down_u_first(self):
        fn = inspect.currentframe().f_code.co_name
        if not self._u_start:
            DEBUG_LOG(fn,"no up server")
            return 
        sel = self._u_start
        self._u_start = self._u_start._next
        if not self._u_start:
            self._u_end = self._u_start
        sel._next = None
        if self._d_end:
            self._d_end._next = sel
            self._d_end = sel
        else:
            self._d_end = sel
            self._d_start = sel
        self._downnum = self._downnum + 1
        DEBUG_LOG(fn,"after_down_sever:downnum",self._downnum)
        return

    
    #
    # 忽略第一个不可用服务器,即将第一个不可用服务器移到down链表最后位置
    # up恢复服务器仍然失败时使用
    #
    def ignore_d_first(self):
        fn = inspect.currentframe().f_code.co_name
        if not self._downnum or not self._d_start:
            DEBUG_LOG(fn,"no down server")
            return
        if self._d_start == self._d_end:
            DEBUG_LOG(fn,"d_start == d_end")
            return
        self._d_end._next = self._d_start
        self._d_end = self._d_start
        self._d_start = self._d_start._next
        self._d_end._next = None
        return 

    
    #
    # 恢复第一个不可用服务器,即将第一个不可用服务器置为可用并加入up链表最后
    #
    def up_d_first(self):
        fn = inspect.currentframe().f_code.co_name
        if not self._downnum or not self._d_start:
            DEBUG_LOG(fn,"no down server")
            return
        sel = self._d_start
        self._d_start = self._d_start._next
        if not self._d_start:
            self._d_end = self._d_start
        self._downnum = self._downnum - 1

        sel._times = sel._mark
        sel._next = None

        if self._u_end:
            self._u_end._next = sel
            self._u_end = sel
        else:
            self._u_end = sel
            self._u_start = sel

        return 

    
    #
    # 选择一台可用服务器的编号返回
    # -1表示无可用服务器
    #
    def select_num(self):
        fn = inspect.currentframe().f_code.co_name
        if not self._u_start:
            DEBUG_LOG(fn,"no up server")
            return -1
        if not self._u_start._times:
            #第一台可用服务器times已经使用完毕，将第一台移到up链表最后位置
            self._u_start._times = self._u_start._mark
            if self._u_start != self._u_end:
                self._u_end._next = self._u_start
                self._u_end = self._u_start
                self._u_start = self._u_start._next
                self._u_end._next = None
        self._u_start._times = self._u_start._times - 1 #使用次数减去1
        return self._u_start._num



if __name__ == '__main__':
    fn = "main"
    c = PY_Cluster_Stat_Manager()
    c.down_u_first()
    c.print_list()

    DEBUG_LOG(fn,"+++++++++++添加两台可用服务")
    c.add_u_server(0,1)
    c.add_u_server(1,2)
    c.print_list()

    DEBUG_LOG(fn,"+++++++++++获取第一个可用服务")
    servernum = c.select_num()
    DEBUG_LOG(fn,"get_server_num",servernum)
    c.print_list()

    DEBUG_LOG(fn,"++++++++++++++down掉所有服务")
    c.down_u_first()
    c.down_u_first()
    c.down_u_first()
    c.print_list()

    DEBUG_LOG(fn,"+++++++++++获取第一个可用服务")
    c.select_num()
    
    DEBUG_LOG(fn,"+++++++++++++启动所有down掉的服务")
    downnum = c.get_down_num()
    DEBUG_LOG(fn,"down掉的server数量",downnum)
    for i in range(0,downnum):
        sel = c.get_d_first()
        DEBUG_LOG(fn,"开始up重启服务：sever_num",sel)
        c.up_d_first()


    DEBUG_LOG(fn,"+++++++++++++打印所有的服务")
    c.print_list()


    exit(0)

    #选择可用服务器
    num = c.select_num()    
    DEBUG_LOG("main::get first server_num",str(num))
    c.print_list()

    #选择可用服务器
    num = c.select_num()    
    DEBUG_LOG("main::get second server_num",str(num))
    c.print_list()

    #选择可用服务器
    num = c.select_num()    
    DEBUG_LOG("main::get three server_num",str(num))
    c.print_list()

    DEBUG_LOG("main::--------------down_u_first-------------------")
    c.down_u_first()
    c.print_list()

    dnum = c.get_d_first()
    DEBUG_LOG("main::get down first server_num",str(dnum))
    c.print_list()

    DEBUG_LOG("main::--------------ignore_d_first-------------------")
    c.ignore_d_first()
    c.print_list()

    DEBUG_LOG("main::--------------up_d_first-------------------")
    c.up_d_first()
    c.print_list()

    #选择可用服务器
    num = c.select_num()    
    DEBUG_LOG("main::get four server_num",str(num))
    c.print_list()

    #选择可用服务器
    num = c.select_num()    
    DEBUG_LOG("main::get five server_num",str(num))
    c.print_list()


